package main

import "fmt"

func main() {
	/*
		1.Go语言中，只有一种参数传递规则：值拷贝
		（1）函数参数传递时使用的是值拷贝
		（2）实例赋值给接口变量，接口对实例的引用是值拷贝

		2.有时明明是值拷贝的地方，结果却修改了变量的内容：
		（1）直接传递的是指针。
				指针同样是值传递，但指针和指针副本的值指向的地址是同一个地方，所以能修改实参值
		（2）参数是复合类型。
				这些复合数据类型内部都有指针类型的元素，此时参数的值拷贝并不影响指针的指向
				eg: chan, map, slice, interface 内部都是通过指针指向具体的数据的

		3.函数名和匿名函数字面量的值有三层含义：
		（1）类型信息，表明其数据是函数类型
		（2）函数名代表函数的执行代码的起始位置
		（3）可以通过函数名进行函数的调用，函数调用的格式为 func_name(param_list)。
			在底层执行层包含以下4部分内容：
			a.准备好参数
			b.修改 PC 值，跳转到函数代码起始位置开始执行
			c.复制值到函数的返回值栈区
			d.通过 RET 返回到函数调用的下一条指令处继续执行

		4.闭包对外部变量的引用：
			可以认为是建立了一个和外部变量同名的“引用”，该引用和外部变量指向相同的地址。
			即，闭包可以访问和改变外部环境中的变量
	*/
	//闭包的例子：

	//f 是一个闭包，包括对函数 fa 形式参数 a 的“同名引用”
	f := fa(1)

	fmt.Println(f(1)) //2
	fmt.Println(f(2)) //4
}

// |*参数*| |*   返回值   *|
func fa(a int) func(i int) int {
	return func(i int) int {
		println(&a, a)
		a = a + i
		return a
	}
}
